package com.ittao.taoaicodemother.manage.storage.lifecycle;

import com.ittao.taoaicodemother.exception.BusinessException;
import com.ittao.taoaicodemother.exception.ErrorCode;
import com.ittao.taoaicodemother.manage.storage.factory.FileStorageStrategyFactory;
import com.ittao.taoaicodemother.manage.storage.lifecycle.tracker.SessionActivityTracker;
import com.ittao.taoaicodemother.manage.storage.strategy.FileStorageStrategy;
import com.ittao.taoaicodemother.manage.storage.strategy.impl.CosFileStorageStrategy;
import com.ittao.taoaicodemother.manage.storage.service.CosOperationService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.nio.file.Path;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * 项目生命周期管理器
 * 管理项目从上传到清理的生命周期：
 * 1. 上传阶段：异步上传整个项目到COS（如果是COS策略）
 * 2. 清理阶段：通过观察者模式管理临时文件生命周期
 * 
 * 注意：构建逻辑已移至门面层处理
 */
@Slf4j
@Component
public class ProjectLifecycleManager {

    @Resource
    private FileStorageStrategyFactory fileStorageStrategyFactory;

    @Resource
    private SessionActivityTracker sessionActivityTracker;

    @Resource
    private CosOperationService cosOperationService;

    @Resource(name = "virtualThreadExecutor")
    private Executor virtualThreadExecutor;

    /**
     * 会话项目缓存映射：sessionId -> ProjectCacheInfo
     */
    private final ConcurrentHashMap<String, ProjectCacheInfo> sessionProjectCache = new ConcurrentHashMap<>();

    /**
     * 处理项目上传和清理流程（不包含构建）
     * 上传 → 通知观察者
     *
     * @param userId 用户ID
     * @param appId 应用ID
     * @param sessionId 会话ID
     * @param localTempPath 本地临时路径
     * @param onSuccess 成功回调
     * @param onError 错误回调
     */
    public void handleProjectUploadAndCleanup(String userId, String appId, String sessionId, Path localTempPath,
                                              Consumer<String> onSuccess, Consumer<Exception> onError) {
        virtualThreadExecutor.execute(() -> {
            try {
                log.info("开始处理项目上传和清理流程，appId: {}, sessionId: {}", appId, sessionId);

                // 发布项目生成开始事件
                sessionActivityTracker.publishProjectGenerationStart(sessionId, userId, appId, localTempPath.toString());

                // 1. 异步上传到COS（如果是COS策略）
                FileStorageStrategy strategy = fileStorageStrategyFactory.getCurrentStrategy();
                if (strategy instanceof CosFileStorageStrategy) {
                    String projectName = "vue_project_" + appId;
                    String cosPath = "userApp/" + userId + "/code_output/" + projectName;
                    boolean uploadSuccess = cosOperationService.uploadBuildResults(
                            localTempPath.toString(),
                            cosPath
                    );
                    if (!uploadSuccess) {
                        throw new BusinessException(ErrorCode.SYSTEM_ERROR, "项目上传失败");
                    }
                    log.info("项目上传成功，appId: {}", appId);

                    // 2. 缓存项目信息
                    ProjectCacheInfo cacheInfo = new ProjectCacheInfo(sessionId, userId, appId, localTempPath);
                    sessionProjectCache.put(sessionId, cacheInfo);

                    // 3. 发布项目生成完成事件，触发观察者开始监控
                    sessionActivityTracker.publishProjectGenerationComplete(sessionId, userId, appId, localTempPath.toString());
                    log.info("项目上传和清理流程完成，appId: {}, 已启动观察者监控", appId);
                } else {
                    // 本地存储策略，不需要上传和清理
                    log.info("本地存储策略，项目已保存到本地，无需上传和清理，appId: {}", appId);
                }

                if (onSuccess != null) {
                    onSuccess.accept("项目处理成功");
                }

            } catch (Exception e) {
                log.error("项目上传和清理流程失败，appId: {}, error: {}", appId, e.getMessage(), e);

                if (onError != null) {
                    onError.accept(e);
                }
            }
        });
    }

    /**
     * 项目缓存信息类
     */
    private record ProjectCacheInfo(String sessionId, String userId, String appId, Path localTempPath) {
    }
}